home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH4 / SRC / SUBEDGE.FRM (.txt) < prev    next >
Encoding:
Visual Basic Form  |  1997-01-03  |  13.7 KB  |  437 lines

  1. VERSION 4.00
  2. Begin VB.Form SubEdgeForm 
  3.    Caption         =   "SubEdge"
  4.    ClientHeight    =   4845
  5.    ClientLeft      =   1170
  6.    ClientTop       =   1215
  7.    ClientWidth     =   7110
  8.    Height          =   5535
  9.    Left            =   1110
  10.    LinkTopic       =   "Form1"
  11.    ScaleHeight     =   323
  12.    ScaleMode       =   3  'Pixel
  13.    ScaleWidth      =   474
  14.    Top             =   585
  15.    Width           =   7230
  16.    Begin VB.PictureBox ToPict 
  17.       AutoRedraw      =   -1  'True
  18.       Height          =   4815
  19.       Left            =   3600
  20.       Picture         =   "SUBEDGE.frx":0000
  21.       ScaleHeight     =   317
  22.       ScaleMode       =   3  'Pixel
  23.       ScaleWidth      =   229
  24.       TabIndex        =   1
  25.       Top             =   0
  26.       Width           =   3495
  27.    End
  28.    Begin VB.PictureBox FromPict 
  29.       AutoRedraw      =   -1  'True
  30.       Height          =   4815
  31.       Left            =   0
  32.       ScaleHeight     =   317
  33.       ScaleMode       =   3  'Pixel
  34.       ScaleWidth      =   229
  35.       TabIndex        =   0
  36.       Top             =   0
  37.       Width           =   3495
  38.    End
  39.    Begin MSComDlg.CommonDialog FileDialog 
  40.       Left            =   3360
  41.       Top             =   0
  42.       _Version        =   65536
  43.       _ExtentX        =   847
  44.       _ExtentY        =   847
  45.       _StockProps     =   0
  46.       CancelError     =   -1  'True
  47.    End
  48.    Begin VB.Menu mnuFile 
  49.       Caption         =   "&File"
  50.       Begin VB.Menu mnuFileLoad 
  51.          Caption         =   "&Load..."
  52.          Shortcut        =   ^L
  53.       End
  54.       Begin VB.Menu mnuFileSep2 
  55.          Caption         =   "-"
  56.       End
  57.       Begin VB.Menu mnuFileExit 
  58.          Caption         =   "E&xit"
  59.       End
  60.    End
  61. Attribute VB_Name = "SubEdgeForm"
  62. Attribute VB_Creatable = False
  63. Attribute VB_Exposed = False
  64. Option Explicit
  65. Dim SysPalSize As Integer
  66. Dim NumStaticColors As Integer
  67. Dim StaticColor1 As Integer
  68. Dim StaticColor2 As Integer
  69. Dim LogPal As Integer
  70. Dim bytes() As Byte
  71. Dim wid As Long
  72. Dim hgt As Long
  73. Dim palentry(0 To 255) As PALETTEENTRY
  74. ' ************************************************
  75. ' Return the index of the nonstatic gray closest
  76. ' to the given value (assuming the non-static
  77. ' colors are a gray scale created by
  78. ' MatchGrayPalette).
  79. ' ************************************************
  80. Function NearestNonstaticGray(c As Integer) As Integer
  81. Dim dgray As Single
  82.     If c < 0 Then
  83.         c = 0
  84.     ElseIf c > 255 Then
  85.         c = 255
  86.     End If
  87.     dgray = 255 / (StaticColor2 - StaticColor1 - 2)
  88.     NearestNonstaticGray = c / dgray + StaticColor1 + 1
  89. End Function
  90. ' ***********************************************
  91. ' Load the indicated file and prepare to work
  92. ' with its palette.
  93. ' ***********************************************
  94. Sub LoadFromPict(fname As String)
  95. Dim i As Integer
  96.     On Error GoTo LoadFileError
  97.     FromPict.Picture = LoadPicture(fname)
  98.     On Error GoTo 0
  99.     MatchGrayPalette FromPict
  100.     Caption = "SubEdge [" & fname & "]"
  101.     Exit Sub
  102. LoadFileError:
  103.     Beep
  104.     MsgBox "Error loading file " & fname & "." & _
  105.         vbCrLf & Error$
  106.     Exit Sub
  107. End Sub
  108. ' ************************************************
  109. ' Subtract the image from itself shifted +1 pixel
  110. ' in the X and Y directions to highlight edges.
  111. ' ************************************************
  112. Sub SubtractEdges()
  113. Dim x As Integer
  114. Dim y As Integer
  115. Dim result() As Byte
  116. Dim status As Long
  117. Dim c1 As Integer
  118. Dim c2 As Integer
  119.     ToPict.Picture = FromPict.Image
  120.     ' Subtract the image.
  121.     ReDim result(1 To wid, 1 To hgt)
  122.     For y = 1 To hgt - 1
  123.         For x = 1 To wid - 1
  124.             With palentry(bytes(x + 1, y + 1))
  125.                 c1 = (CInt(.peRed) + .peGreen + .peBlue) / 3
  126.             End With
  127.             With palentry(bytes(x, y))
  128.                 c2 = (CInt(.peRed) + .peGreen + .peBlue) / 3
  129.             End With
  130.             result(x, y) = _
  131.                 NearestNonstaticGray(Abs(c1 - c2))
  132.         Next x
  133.     Next y
  134.     ' Black out edges where there's no subtraction.
  135.     For y = 1 To hgt
  136.         result(wid, y) = StaticColor1 + 1
  137.     Next y
  138.     For x = 1 To wid
  139.         result(x, hgt) = StaticColor1 + 1
  140.     Next x
  141.     ' Display the result.
  142.     status = SetBitmapBits(ToPict.Image, wid * hgt, result(1, 1))
  143.     ToPict.Refresh
  144.     ' Let ToPict rerealize its palette.
  145.     ToPict.ZOrder
  146. End Sub
  147. ' ***********************************************
  148. ' Load the control's palette so it matches the
  149. ' the system palette. Remap any of the image's
  150. ' pixels that use static colors to non-static
  151. ' colors.
  152. ' Set the following module global variables.
  153. '   LogPal      Image logical palette handle.
  154. '   palentry()  Image logical palette entries.
  155. '   wid         Width of image.
  156. '   hgt         Height of image.
  157. '   bytes(1 To wid, 1 To hgt)
  158. '               Image pixel values.
  159. ' ***********************************************
  160. Sub MatchColorPalette(pic As Control)
  161. Dim sys(0 To 255) As PALETTEENTRY
  162. Dim i As Integer
  163. Dim bm As BITMAP
  164. Dim hbm As Integer
  165. Dim status As Long
  166. Dim x As Integer
  167. Dim y As Integer
  168. Dim clr As Integer
  169.     ' Make sure pic has the foreground palette.
  170.     pic.ZOrder
  171.     i = RealizePalette(pic.hdc)
  172.     DoEvents
  173.     ' Get the system palette entries.
  174.     i = GetSystemPaletteEntries(pic.hdc, 0, SysPalSize, sys(0))
  175.             
  176.     ' Make the logical palette as big as possible.
  177.     LogPal = pic.Picture.hPal
  178.     If ResizePalette(LogPal, SysPalSize) = 0 Then
  179.         Beep
  180.         MsgBox "Error resizing logical palette.", _
  181.             vbExclamation
  182.         Exit Sub
  183.     End If
  184.     ' Blank the non-static colors.
  185.     For i = 0 To StaticColor1
  186.         palentry(i) = sys(i)
  187.     Next i
  188.     For i = StaticColor1 + 1 To StaticColor2 - 1
  189.         With palentry(i)
  190.             .peRed = 0
  191.             .peGreen = 0
  192.             .peBlue = 0
  193.             .peFlags = PC_NOCOLLAPSE
  194.         End With
  195.     Next i
  196.     For i = StaticColor2 To 255
  197.         palentry(i) = sys(i)
  198.     Next i
  199.     i = SetPaletteEntries(LogPal, 0, SysPalSize, palentry(0))
  200.     ' Insert the non-static colors.
  201.     For i = StaticColor1 + 1 To StaticColor2 - 1
  202.         palentry(i) = sys(i)
  203.         palentry(i).peFlags = PC_NOCOLLAPSE
  204.     Next i
  205.     i = SetPaletteEntries(LogPal, StaticColor1 + 1, StaticColor2 - StaticColor1 - 1, palentry(StaticColor1 + 1))
  206.     ' Realize the new palette.
  207.     i = RealizePalette(pic.hdc)
  208.     ' Get the image pixels.
  209.     hbm = pic.Image
  210.     status = GetObject(hbm, BITMAP_SIZE, bm)
  211.     wid = bm.bmWidthBytes
  212.     hgt = bm.bmHeight
  213.     ReDim bytes(1 To wid, 1 To hgt)
  214.     status = GetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  215.     ' Remap any pixels using static colors.
  216.     For y = 1 To hgt
  217.         For x = 1 To wid
  218.             clr = bytes(x, y)
  219.             If clr <= StaticColor1 Or clr >= StaticColor2 Then
  220.                 With sys(clr)
  221.                     bytes(x, y) = _
  222.                         NearestNonstaticColor( _
  223.                         .peRed, .peGreen, .peBlue)
  224.                 End With
  225.             End If
  226.         Next x
  227.     Next y
  228.     ' Update the image's pixel values.
  229.     status = SetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  230.     pic.Refresh
  231. End Sub
  232. ' ***********************************************
  233. ' Load the control's palette so the non-static
  234. ' colors are grays. Map the logical palette to
  235. ' match the system palette. Convert the image to
  236. ' use the non-static grays.
  237. ' Set the following module global variables.
  238. '   LogPal      Image logical palette handle.
  239. '   palentry()  Image logical palette entries.
  240. '   wid         Width of image.
  241. '   hgt         Height of image.
  242. '   bytes(1 To wid, 1 To hgt)
  243. '               Image pixel values.
  244. ' ***********************************************
  245. Sub MatchGrayPalette(pic As Control)
  246. Dim sys(0 To 255) As PALETTEENTRY
  247. Dim i As Integer
  248. Dim bm As BITMAP
  249. Dim hbm As Integer
  250. Dim status As Long
  251. Dim x As Integer
  252. Dim y As Integer
  253. Dim gray As Single
  254. Dim dgray As Single
  255. Dim c As Integer
  256. Dim clr As Integer
  257.     ' Make sure pic has the foreground palette.
  258.     pic.ZOrder
  259.     i = RealizePalette(pic.hdc)
  260.     DoEvents
  261.     ' Get the system palette entries.
  262.     i = GetSystemPaletteEntries(pic.hdc, 0, SysPalSize, sys(0))
  263.         
  264.     ' Get the image pixels.
  265.     hbm = pic.Image
  266.     status = GetObject(hbm, BITMAP_SIZE, bm)
  267.     wid = bm.bmWidthBytes
  268.     hgt = bm.bmHeight
  269.     ReDim bytes(1 To wid, 1 To hgt)
  270.     status = GetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  271.     ' Make the logical palette as big as possible.
  272.     LogPal = pic.Picture.hPal
  273.     If ResizePalette(LogPal, SysPalSize) = 0 Then
  274.         Beep
  275.         MsgBox "Error resizing logical palette.", _
  276.             vbExclamation
  277.         Exit Sub
  278.     End If
  279.     ' Blank the non-static colors.
  280.     For i = 0 To StaticColor1
  281.         palentry(i) = sys(i)
  282.     Next i
  283.     For i = StaticColor1 + 1 To StaticColor2 - 1
  284.         With palentry(i)
  285.             .peRed = 0
  286.             .peGreen = 0
  287.             .peBlue = 0
  288.             .peFlags = PC_NOCOLLAPSE
  289.         End With
  290.     Next i
  291.     For i = StaticColor2 To 255
  292.         palentry(i) = sys(i)
  293.     Next i
  294.     i = SetPaletteEntries(LogPal, 0, SysPalSize, palentry(0))
  295.     ' Insert the non-static grays.
  296.     gray = 0
  297.     dgray = 255 / (StaticColor2 - StaticColor1 - 2)
  298.     For i = StaticColor1 + 1 To StaticColor2 - 1
  299.         c = gray
  300.         gray = gray + dgray
  301.         With palentry(i)
  302.             .peRed = c
  303.             .peGreen = c
  304.             .peBlue = c
  305.         End With
  306.     Next i
  307.     i = SetPaletteEntries(LogPal, StaticColor1 + 1, StaticColor2 - StaticColor1 - 1, palentry(StaticColor1 + 1))
  308.     ' Recreate the image using the new colors.
  309.     For y = 1 To hgt
  310.         For x = 1 To wid
  311.             clr = bytes(x, y)
  312.             With sys(clr)
  313.                 c = (CInt(.peRed) + .peGreen + .peBlue) / 3
  314.             End With
  315.             bytes(x, y) = NearestNonstaticGray(c)
  316.         Next x
  317.     Next y
  318.     status = SetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  319.     ' Realize the gray palette.
  320.     i = RealizePalette(pic.hdc)
  321.     pic.Refresh
  322. End Sub
  323. ' ************************************************
  324. ' Return the index of the nonstatic color closest
  325. ' to the given color value.
  326. ' ************************************************
  327. Function NearestNonstaticColor(ByVal r As Integer, ByVal g As Integer, ByVal b As Integer) As Integer
  328. Dim best_i As Integer
  329. Dim best_dist As Long
  330. Dim dist As Long
  331. Dim dr As Long
  332. Dim dg As Long
  333. Dim db As Long
  334. Dim i As Integer
  335.     best_dist = 1000000
  336.     For i = StaticColor1 + 1 To StaticColor2 - 1
  337.         With palentry(i)
  338.             dr = r - .peRed
  339.             dg = g - .peGreen
  340.             db = b - .peBlue
  341.             dist = dr * dr + dg * dg + db * db
  342.         End With
  343.         If best_dist > dist Then
  344.             best_i = i
  345.             best_dist = dist
  346.         End If
  347.     Next i
  348.     NearestNonstaticColor = best_i
  349. End Function
  350. ' ***********************************************
  351. ' Give the form and all the picture boxes an
  352. ' hourglass cursor.
  353. ' ***********************************************
  354. Sub WaitStart()
  355.     MousePointer = vbHourglass
  356.     FromPict.MousePointer = vbHourglass
  357.     ToPict.MousePointer = vbHourglass
  358.     DoEvents
  359. End Sub
  360. ' ***********************************************
  361. ' Restore the mouse pointers for the form and all
  362. ' the picture boxes.
  363. ' ***********************************************
  364. Sub WaitEnd()
  365.     MousePointer = vbDefault
  366.     FromPict.MousePointer = vbDefault
  367.     ToPict.MousePointer = vbDefault
  368. End Sub
  369. Private Sub Form_Load()
  370.     ' Make sure the screen supports palettes.
  371.     If Not GetDeviceCaps(hdc, RASTERCAPS) And RC_PALETTE Then
  372.         Beep
  373.         MsgBox "This monitor does not support palettes.", _
  374.             vbCritical
  375.         End
  376.     End If
  377.     ' Get system palette size and # static colors.
  378.     SysPalSize = GetDeviceCaps(hdc, SIZEPALETTE)
  379.     NumStaticColors = GetDeviceCaps(hdc, NUMRESERVED)
  380.     StaticColor1 = NumStaticColors \ 2 - 1
  381.     StaticColor2 = SysPalSize - NumStaticColors \ 2
  382.     ' Make ToPict use grays.
  383.     MatchGrayPalette ToPict
  384. End Sub
  385. ' ***********************************************
  386. ' Make the picture as large as possible.
  387. ' ***********************************************
  388. Private Sub Form_Resize()
  389. Const GAP = 4
  390. Dim hgt As Single
  391. Dim wid As Single
  392.     If WindowState = vbMinimized Then Exit Sub
  393.         
  394.     hgt = ScaleHeight
  395.     wid = (ScaleWidth - GAP - 1) / 2
  396.     FromPict.Move 0, 0, wid, hgt
  397.     ToPict.Move FromPict.Width + GAP, 0, wid, hgt
  398. End Sub
  399. Private Sub Form_Unload(Cancel As Integer)
  400.     End
  401. End Sub
  402. ' ***********************************************
  403. ' Load a new image file.
  404. ' ***********************************************
  405. Private Sub mnuFileLoad_Click()
  406. Dim fname As String
  407.     ' Allow the user to pick a file.
  408.     On Error Resume Next
  409.     FileDialog.filename = "*.BMP;*.ICO;*.RLE;*.WMF;*.DIB"
  410.     FileDialog.Flags = cdlOFNFileMustExist + cdlOFNHideReadOnly
  411.     FileDialog.ShowOpen
  412.     If Err.Number = cdlCancel Then
  413.         Exit Sub
  414.     ElseIf Err.Number <> 0 Then
  415.         Beep
  416.         MsgBox "Error selecting file.", , vbExclamation
  417.         Exit Sub
  418.     End If
  419.     On Error GoTo 0
  420.     fname = Trim$(FileDialog.filename)
  421.     FileDialog.InitDir = Left$(fname, Len(fname) _
  422.         - Len(FileDialog.FileTitle) - 1)
  423.     ' Load the picture.
  424.     WaitStart
  425.     DoEvents
  426.     LoadFromPict fname
  427.     SubtractEdges
  428.     WaitEnd
  429. End Sub
  430. ' ***********************************************
  431. ' End the application. (See also the QueryUnload
  432. ' event.)
  433. ' ***********************************************
  434. Private Sub mnuFileExit_Click()
  435.     Unload Me
  436. End Sub
  437.